package com.jhws.core.exception;

import java.io.IOException;
import java.util.Arrays;
import java.util.HashMap;
import java.util.Map;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.apache.shiro.web.util.WebUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.http.HttpStatus;
import org.springframework.http.MediaType;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.method.HandlerMethod;
import org.springframework.web.servlet.ModelAndView;
import org.springframework.web.servlet.handler.SimpleMappingExceptionResolver;

import com.jhws.util.GsonUtil;

/**
 * 全局异常处理器
 *
 * @author xiaokek
 * @since 2015年11月2日 下午11:08:22
 */
public class ExceptionResolver extends SimpleMappingExceptionResolver {

    private Logger log = LoggerFactory.getLogger(ExceptionResolver.class);

    @Override
    protected ModelAndView doResolveException(HttpServletRequest request,
                                              HttpServletResponse response, Object handler, Exception e) {

        if (handler instanceof HandlerMethod) {
            HandlerMethod method = (HandlerMethod) handler;
            ResponseBody body = method.getMethodAnnotation(ResponseBody.class);
            if (body == null) {
                e.printStackTrace();
                ModelAndView modelAndView = new ModelAndView();
                /* 根据不同的异常类型传入显示文本 */
                if (e instanceof org.apache.shiro.authz.UnauthorizedException) {
                    modelAndView.addObject("httpStatus", response.getStatus());
                    modelAndView.addObject("content", "哎哟喂！页面发生了错误！您无权限执行此操作！");
                    modelAndView.addObject("errorInfo", Arrays.toString(e.getStackTrace()));
                } else {
                    if (WebUtils.toHttp(request).getRequestURL().toString().contains("8081/LoginCtrl/loginindex.x")) {
                        modelAndView.setViewName("login");
                        return modelAndView;
                    }
                    modelAndView.addObject("httpStatus", response.getStatus());
                    modelAndView.addObject("content", "哎哟喂！页面发生了错误！");
                    modelAndView.addObject("errorInfo", Arrays.toString(e.getStackTrace()));
                }
                modelAndView.setViewName("error/web-api-error");
                return modelAndView;
            }
        }

        response.setContentType(MediaType.APPLICATION_JSON_VALUE);
        response.setCharacterEncoding("UTF-8");
        response.setHeader("Cache-Control", "no-cache, must-revalidate");
        response.setStatus(HttpStatus.OK.value());
        Map<String, String> result = new HashMap<String, String>();
        if (e instanceof BizException) {
            BizException be = (BizException) e;
            result.put("ret_code", be.code);
            result.put("type", be.type);
            result.put("data", be.msg);
            log.info("业务提示：{} 发生在：{}", new Object[]{be.msg, be.getStackTrace()[0].toString()});
        } else if (e instanceof UnauthorizedException) {
            //response.setStatus(HttpStatus.UNAUTHORIZED.value());
            UnauthorizedException be = (UnauthorizedException) e;
            result.put("ret_code", be.code);
            result.put("type", be.type);
            result.put("data", be.msg);
            log.warn("权限安全检查失败：{} 发生在：{}", new Object[]{be.code + ":" + be.msg, be.getStackTrace()[0].toString()});
        } else if(e instanceof org.apache.shiro.authz.AuthorizationException){

            result.put("ret_code", "-407");
            result.put("type", "");
            result.put("data", "您没有访问该资源的权限");
            e.printStackTrace();
        } else {
            result.put("type", "Unknown");
            result.put("ret_code", "-999");
            result.put("data", "内部错误！" + e.getMessage());
            log.error("系统严重错误", e);
        }
        try {
            response.getWriter().write(GsonUtil.toJson(result));
        } catch (IOException ie) {
            ie.printStackTrace();
        }
        return new ModelAndView();
    }

}